package com.io.dao.impl;

import com.io.dao.BaseDaoI;
import com.io.entity.BaseEntity;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * The class/interface
 *
 * @author guodd
 * @version 1.0 use jdk 1.8
 */
public class BaseDaoImpl<T, ID> extends SimpleJpaRepository<T, ID> implements BaseDaoI<T, ID> {
    private final EntityManager entityManager;

    public BaseDaoImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
    }

    @Override
    public <S extends T> S doSave(S o) {
        if (BaseEntity.class.isAssignableFrom(o.getClass())) {
            BaseEntity b = (BaseEntity) o;
            b.setCreateTime(LocalDateTime.now());
            b.setUpdateTime(b.getCreateTime());
        }
        entityManager.persist(o);
        return o;
    }

    @Override
    public void doUpdate(T o) {
        if (!StringUtils.isEmpty(o)) {
            entityManager.merge(o);
        }
    }

    @Override
    public void doDelete(T o) {
        if (!StringUtils.isEmpty(o)) {
            entityManager.remove(o);
        }
    }

    @Override
    public T loadEntity(Class<T> c, Serializable id) {
        return entityManager.getReference(c, id);
    }

    @Override
    public T getEntity(Class<T> c, Serializable l) {
        return entityManager.find(c, l);
    }

    @Override
    public T getEntity(String jpql) {
        Query query = entityManager.createQuery(jpql);
        query.getSingleResult();
        return (T) query.getSingleResult();
    }

    @Override
    public T getEntity(String jpql, Object... params) {
        Query query = entityManager.createQuery(jpql);
        if (params != null && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i + 1, params[i]);
            }
        }
        return (T) query.getSingleResult();
    }

    @Override
    public T getEntity(String jpql, Map<String, Object> params) {
        Query q = entityManager.createQuery(jpql);
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                q.setParameter(key, params.get(key));
            }
        }
        return (T) q.getSingleResult();
    }
}
